package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

/// 由以下命令发现每个请求都有一个SYNC
// tcpdump -i lo tcp dst port 24756 -nn > a
// grep -o 'IP.*\[S\]' a | sort | uniq |wc -l

// https://stackoverflow.com/a/30807688/6328514

const (
    MaxIdleConnections int = 200
    RequestTimeout     int = 5
)

// createHTTPClient for connection re-use
func createHTTPClient() *http.Client {
    client := &http.Client{
        Transport: &http.Transport{
            MaxIdleConnsPerHost: MaxIdleConnections,
        },
        Timeout: time.Duration(RequestTimeout) * time.Second,
    }

    return client
}

func tHttpShortConn() {
	httpClient := createHTTPClient()

    endPoint := "http://localhost:24756/hello"

    req, err := http.NewRequest("POST", endPoint, bytes.NewBuffer([]byte("hello")))
    if err != nil {
        log.Fatalf("Error Occured. %+v, req: %v", err, req)
    }
    //req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	for i:=0; i<10; i++ {
		////////// 仍然是每个请求独自创建了连接 !!!

		response, err := httpClient.Do(req)
		if err != nil && response == nil {
			log.Fatalf("Error sending request to API endpoint. %+v", err)
		}

		// Let's check if the work actually is done
		// We have seen inconsistencies even when we get 200 OK response
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			log.Fatalf("Couldn't parse response body. %+v", err)
		}
		response.Body.Close()

		log.Println("Response Body:", string(body))
	
	} 
}

func tHttpLongConn() {
	httpClient := createHTTPClient()

    endPoint := "http://localhost:24756/hello"

	for i:=0; i<10; i++ {
		// 每次请求前创建新的req
		req, err := http.NewRequest("POST", endPoint, bytes.NewBuffer([]byte("hello")))
		if err != nil {
			log.Fatalf("Error Occured. %+v, req: %v", err, req)
		}
	
		response, err := httpClient.Do(req)

		/// 用了 Post() 就是长连接，用 Do() 就是短连接，why ???
		//response, err := httpClient.Post(endPoint, "application/x-www-form-urlencoded", bytes.NewBuffer([]byte("hello")))

		if err != nil && response == nil {
			log.Fatalf("Error sending request to API endpoint. %+v", err)
		}

		// Let's check if the work actually is done
		// We have seen inconsistencies even when we get 200 OK response

		//////// 以下证明：注释掉 Body.Close() 仍然是长连接，但继续注释掉 ReadAll就不行了，连接没有reuse
		body, err := ioutil.ReadAll(response.Body)
		// n, err := io.Copy(ioutil.Discard, resp.Body) // 这样写也行
		if err != nil {
			log.Fatalf("Couldn't parse response body. %+v", err)
		}
		///response.Body.Close()

		log.Println("Response Body:", string(body))
	
	} 
}